package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.anno.GuiGuCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author Petrichor
 */
@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	private final AlbumAttributeValueMapper albumAttributeValueMapper;
	private final AlbumInfoMapper albumInfoMapper;
	private final AlbumStatMapper albumStatMapper;
	private final KafkaService kafkaService;
	private final RedisTemplate<String,String> redisTemplate;
	@Autowired
	public AlbumInfoServiceImpl(AlbumAttributeValueMapper albumAttributeValueMapper, AlbumInfoMapper albumInfoMapper, AlbumStatMapper albumStatMapper, KafkaService kafkaService, RedisTemplate<String, String> redisTemplate) {
		this.albumAttributeValueMapper = albumAttributeValueMapper;
		this.albumInfoMapper = albumInfoMapper;
		this.albumStatMapper = albumStatMapper;
		this.kafkaService = kafkaService;
		this.redisTemplate = redisTemplate;
	}

	/**
	 * @description: 新增专辑信息
	 * @author Petrichor
	 * @date 2023/12/21 19:42
	 * @param albumInfo 前端传来的专辑信息
	 * @return NULL
	 **/
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveAlbumInfo(AlbumInfo albumInfo) {
		// 1.将前端传来的数据放入 专辑基本信息表 [album_info]
		// 1.1 初始化userId 默认值1 为了后续能查到数据
		albumInfo.setUserId(1L);
		// 1.2 并设置初始化状态为审核通过
		albumInfo.setStatus("1");
		// 1.3 如果是付费专辑则设置前五集为免费试看
		if (!SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())){
			albumInfo.setTracksForFree(5);
		}
		albumInfoMapper.insert(albumInfo);

		// 2. 对数据 放入 专辑属性值表 [AlbumAttributeValue]
		List<AlbumAttributeValue> albumAttributeValueVoList = albumInfo.getAlbumAttributeValueVoList();
		albumAttributeValueVoList
				.stream()
				.map( albumAttributeValueVo -> {
						AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue() ;
						albumAttributeValue.setAlbumId(albumInfo.getId());
						BeanUtils.copyProperties(albumAttributeValueVo , albumAttributeValue);
						return albumAttributeValue ;
					})
				.forEach(
						albumAttributeValue -> albumAttributeValueMapper.insert(albumAttributeValue)
					);
		// 3. 专辑统计表 [albumStat]
		saveTrackStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY);
		saveTrackStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);
		saveTrackStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE);
		saveTrackStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT);
		// 判断是否公开 1 需要公开
		if ("1".equals(albumInfo.getIsOpen())){
			this.kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_UPPER,String.valueOf(albumInfo.getId()));
		}
	}

	/**
	 * @description:  查询当前用户专辑分页列表
	 * @author Petrichor
	 * @date 2023/12/21 20:30
	 * @param page 当前页数
	 * @param limit 当前页面的条数
	 * @param albumInfoQuery 待条件查询
	 * @return 分页 Page 对象
	 **/
	@Override
	public IPage<AlbumListVo> findByPage(Integer page, Integer limit, AlbumInfoQuery albumInfoQuery) {
		Long userId = AuthContextHolder.getUserId();
		albumInfoQuery.setUserId(userId);
		Page<AlbumListVo> pageInfo = new Page<>(page , limit) ;
		// 查询完毕以后，mybatis plus会自动将查询到的数据以及分页所需要的结果数据直接封装到Page对象
		IPage<AlbumListVo> albumListVoIPage = albumInfoMapper.findByPage(pageInfo , albumInfoQuery) ;
		return albumListVoIPage;
	}
	/**
	 * @description: 根据专辑 id删除专辑
	 * @author Petrichor
	 * @date 2023/12/21 21:20
	 * @param id 专辑id
	 * @return NULL
	 **/
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeAlbumInfoById(Long id) {
		// 1.专辑基本信息表 [album_info]
		albumInfoMapper.deleteById(id);
		// 2.专辑属性值表 [AlbumAttributeValue]
		LambdaQueryWrapper<AlbumAttributeValue> albumAttributeValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
		albumAttributeValueLambdaQueryWrapper.eq(AlbumAttributeValue::getAlbumId, id);
		albumAttributeValueMapper.delete(albumAttributeValueLambdaQueryWrapper);
		// 3.专辑统计表 [albumStat]
		LambdaQueryWrapper<AlbumStat> albumStatLambdaQueryWrapper = new LambdaQueryWrapper<>();
		albumStatLambdaQueryWrapper.eq(AlbumStat::getAlbumId, id);
		albumStatMapper.delete(albumStatLambdaQueryWrapper);
		// 发送下架
		this.kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_LOWER,String.valueOf(id));
	}
	/**
	 * @description: 根据id获取专辑 getAlbumInfoFromDataBase
	 * @author Petrichor
	 * @date 2023/12/21 22:41
	 * @param id 专辑id
	 * @return 返回专辑信息
	 **/
	@GuiGuCache(
			cacheKey = RedisConstant.ALBUM_INFO_PREFIX + "#{#params[0]}" ,
			enableLock = true ,
			lockName = RedisConstant.ALBUM_LOCK_SUFFIX + "#{#params[0]}"
	)
	@Override
	public AlbumInfo getAlbumInfo(Long id) {
		//	根据id 查询专辑数据
		AlbumInfo albumInfo = this.getById(id);
		//	回显时，需要回显专辑数据信息数据
		if (albumInfo!=null){
			List<AlbumAttributeValue> albumAttributeValueList =
					albumAttributeValueMapper.
							selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));
			albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList);
		}
		return albumInfo;
	}
	/**
	 * @description: 根据id修改专辑
	 * @author Petrichor
	 * @date 2023/12/21 22:53
	 * @param id 专辑id
	 * @return NULL
	 **/
	@Override
	public void updateAlbumInfo(Long id, AlbumInfoVo albumInfoVo) {
		//延迟双删策略 <1>删除缓存
		redisTemplate.delete(RedisConstant.ALBUM_INFO_PREFIX+id);
		// 根据id 修改数据
		AlbumInfo albumInfo = this.getById(id);
		BeanUtils.copyProperties(albumInfoVo, albumInfo);
		this.updateById(albumInfo);

		//	先删除专辑属性数据
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,id));

		//	保存专辑属性数据
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		if (!CollectionUtils.isEmpty(albumAttributeValueVoList)){
			albumAttributeValueVoList.forEach(albumAttributeValueVo -> {
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();		//	创建专辑属性对象
				BeanUtils.copyProperties(albumAttributeValueVo,albumAttributeValue);		//	进行数据拷贝
				albumAttributeValue.setAlbumId(id);											//	赋值专辑属性Id
				albumAttributeValueMapper.insert(albumAttributeValue);
			});
		}
		//延迟双删策略 <2> 休眠 + 再删除
		try {

			// 线程休眠
			TimeUnit.MILLISECONDS.sleep(200);

			// 进行第二次删除
			redisTemplate.delete(RedisConstant.ALBUM_INFO_PREFIX + id) ;

		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		// 判断是否公开
		if ("1".equals(albumInfo.getIsOpen())){
			this.kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_UPPER,String.valueOf(id));
		}else {
			this.kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_LOWER, String.valueOf(id));
		}
	}
	/**
	 * @description: 获取当前用户全部专辑列表
	 * @author Petrichor
	 * @date 2023/12/22 16:17
	 * @return AlbumInfo
	 **/
	@Override
	public List<AlbumInfo> findUserAllAlbumList() {
		// 创建查询 专辑信息
		AlbumInfo albumInfo = new AlbumInfo();
		// 查询用户id
		Long userId = AuthContextHolder.getUserId();
		// 构建查询条件对象
		LambdaQueryWrapper<AlbumInfo> albumInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
		albumInfoLambdaQueryWrapper
				// userId 等于当前用户
				.eq(AlbumInfo::getUserId, userId)
				// 只需要查询 专辑Id 和 专辑标题
				.select(AlbumInfo::getId,AlbumInfo::getAlbumTitle)
				// 根据专辑Id 从大到小排列
				.orderByDesc(AlbumInfo::getId);

		return albumInfoMapper.selectList(albumInfoLambdaQueryWrapper);
	}
	/**
	 * @description: 根据专辑的id查询专辑的统计数据
	 * @author Petrichor
	 * @date 2023/12/26 21:15
	 * @param albumId 专辑id
	 * @return AlbumStatVo专辑的统计数据
	 **/
	@Override
	@GuiGuCache(
			cacheKey = "album:stat:info:" + "#{#params[0]}",
			enableLock = true ,
			lockName = "album:stat:lock:" + "#{#params[0]}"
	)
	public AlbumStatVo findAlbumStatByAlbumId(Long albumId) {
		return albumStatMapper.findAlbumStatByAlbumId(albumId);
	}
	/**
	 * 初始化统计数据
	 * @param albumId
	 * @param statType
	 */
	private void saveTrackStat(Long albumId, String statType) {
		AlbumStat albumStat = new AlbumStat();
		albumStat.setAlbumId(albumId);
		albumStat.setStatType(statType);
		albumStat.setStatNum(0);
		albumStatMapper.insert(albumStat);
	}
}
